package assist.domain.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.Column;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(detachable = "true")
public class Game implements Serializable, Comparable<Game>
{
    @NotPersistent
    private static final long serialVersionUID = 1L;    
    @PrimaryKey
    @Persistent
    @Column(length=20)
    private String id;  
    
    @Persistent 
    private Date date;
    
    @Persistent 
    private String homeTeamId;   
    @Persistent 
    private String visitorTeamId;   
    
    
    @NotPersistent
    private transient Team homeTeam;    
    @NotPersistent
    private transient Team visitorTeam;    
    
    /**
     * GameStats contains the Rosters and Stats for each team.  There are 2 
     * GameStats in each game, one for home team and one for visiting team. JDO
     * will not allow 2 fields the same type, which is why it is a List.
     * TODO: Could this be Map instead of List?
     
    Persistent(defaultFetchGroup="true")
    */
    @NotPersistent
    private transient List<GameStats> stats = new ArrayList<GameStats>();

    //TODO: Remove all the stats below, replaced by GameStats above.
    @NotPersistent 
    private transient Shots homeShots = new Shots();
    @NotPersistent 
    private transient Shots visitorShots = new Shots();
    //TODO: Move Penalties and Faceoffs to GameStats, and make persistable.
    //TODO: Penalties should be own collection with helper methods, like Shots
    @NotPersistent 
    private transient List<Penalty> homePenalties = new ArrayList<Penalty>();
    @NotPersistent 
    private transient List<Penalty> visitorPenalties = new ArrayList<Penalty>();
    //TODO: Faceoffs should be own collection with helper methods, like Shots
    @NotPersistent 
    private transient List<Faceoff> homeFaceoffWins = new ArrayList<Faceoff>();
    @NotPersistent 
    private transient  List<Faceoff> visitorFaceoffWins = new ArrayList<Faceoff>();    
           
    public Game()
    {
        this.stats.add(new GameStats());
        this.stats.add(new GameStats());
    }
    
    @Override
    public String toString()
    {
        return this.id;
    }
    
    @Override
    public int hashCode()
    {    
        return this.id.hashCode();
    }
    
    @Override
    public boolean equals(Object obj)
    {
        String id = "";      
        if (obj instanceof Game)
        {
            id = ((Game)obj).getId();
            
        }
        else if (obj instanceof String)
        {
            id = (String) obj;            
        }        
           
        return id.equals(this.id);
    }
    
    public String getId()
    {
        return this.id;
    }
    public void setId(final String id)
    {
        this.id = id;
    }
    
    /**
     * @return the homeTeam
     */
    public Team getHomeTeam()
    {
        return this.homeTeam;
    }
    /**
     * @param homeTeam the homeTeam to set
     */
    public void setHomeTeam(final Team homeTeam)
    {
        this.homeTeam = homeTeam;
    }
    
    /**
     * @return the visitorTeam
     */
    public Team getVisitorTeam()
    {
        return this.visitorTeam;
    }
    /**
     * @param visitorTeam the visitorTeam to set
     */
    public void setVisitorTeam(final Team visitorTeam)
    {
        this.visitorTeam = visitorTeam;
    }
    
    
    /**
     * Convenience method that returns the roster, given the team abbreviation.
     
    public Roster getRoster(final String teamAbbrev)
    {
        if (teamAbbrev.equalsIgnoreCase(
                this.getHomeRoster().getTeam().getAbbreviation()))
        {
            return this.getHomeRoster();
        }
        if (teamAbbrev.equalsIgnoreCase(
                this.getVisitorRoster().getTeam().getAbbreviation()))
        {
            return this.getVisitorRoster();
        }
        throw new IllegalArgumentException("Team Abbreviation: " + teamAbbrev 
                + " is not found in this Game.");
    }*/
    
    /**
     * @param date the date to set
     */
    public void setDate(final Date date)
    {
        this.date = date;
    }
    /**
     * @return the date
     */
    public Date getDate()
    {
        return this.date;
    }    
    
    public GameStats getGameStats(final Team team)
    {
        if (team.equals(this.homeTeam))
        {
            return this.getHomeGameStats();
        }
        if (team.equals(this.visitorTeam))
        {
            return this.getVisitorGameStats();
        }
        throw new IllegalArgumentException("Team: " + team.getFullName()
                + " is not found in this Game.");
    }    
    
    public GameStats getHomeGameStats()
    {
        return this.stats.get(0);
    }   
    
    public GameStats getVisitorGameStats()
    {
        return this.stats.get(1);
    }       
    
    
    /**
     * Convenience method that returns the shots, given the team abbreviation.
    
    public Shots getShots(final String teamAbbrev)
    {
        if (teamAbbrev.equalsIgnoreCase(
                this.getHomeRoster().getTeam().getAbbreviation()))
        {
            return this.homeShots;
        }
        if (teamAbbrev.equalsIgnoreCase(
                this.getVisitorRoster().getTeam().getAbbreviation()))
        {
            return this.visitorShots;
        }
        throw new IllegalArgumentException("Team Abbreviation: " + teamAbbrev 
                + " is not found in this Game.");
    }    



    
    public void setVisitorShots(final Shots visitorShots)
    {
        this.visitorShots = visitorShots;
    }
    
    public Shots getVisitorShots()
    { 
        return this.visitorShots;
    }
    
    public void setHomeShots(final Shots homeShots)
    {
        this.homeShots = homeShots;
    }
    
    public Shots getHomeShots()
    { 
        return this.homeShots;
    }
 */
    /**
     * @return the homeRoster
    
    public Roster getHomeRoster()
    {
        return this.stats.get(0).getRoster();
    }

    public Roster getVisitorRoster()
    {
        return this.stats.get(1).getRoster();
    } */
    
    /**
     * Adds the given event to this game.  The game contains a variety of 
     * different collections for the Events.  This method adds the event to 
     * the appropriate collection. 
     * @param event The Event to add.
     * @param teamAbbrev The team for the Event, if necessary.  If the event
     * is a shot, then the team is who shot it.  If if is a penalty, then the
     * team is who took the penalty. For faceoffs, team that won faceoff.
     */
    public void addEvent(final Event event, final Team team)
    {
        if (event instanceof Shot)
        {
            Shot shot = (Shot) event;
            this.getGameStats(team).getShots().addShot(shot);
        }
        
        //TODO: Put ALL stats in the GameStats.
        if (event instanceof Penalty)
        {
            if (team.equals(this.homeTeam))
            {
                this.homePenalties.add((Penalty)event);
            }
            if (team.equals(this.visitorTeam))
            {
                this.visitorPenalties.add((Penalty)event);
            }            
        }
        if (event instanceof Faceoff)
        {
            if (team.equals(this.homeTeam))
            {
                this.homeFaceoffWins.add((Faceoff)event);
            }
            if (team.equals(this.visitorTeam))
            {
                this.visitorFaceoffWins.add((Faceoff)event);
            }            
        }        
    }
    
    /**/
    public void clearAll()
    {
        this.getHomeGameStats().clearAll();
        this.getVisitorGameStats().clearAll();
        /*
        this.getHomeShots().clearAll();
        this.getVisitorShots().clearAll();
        */
        this.homePenalties.clear();
        this.visitorPenalties.clear();
        this.visitorFaceoffWins.clear();
        this.homeFaceoffWins.clear();
    }

    /**
     * @return the homePenalties
     */
    public List<Penalty> getHomePenalties()
    {
        return this.homePenalties;
    }

    /**
     * @return the visitorPenalties
     */
    public List<Penalty> getVisitorPenalties()
    {
        return this.visitorPenalties;
    }

    /**
     * @return the visitorFaceoffWins
     */
    public List<Faceoff> getVisitorFaceoffWins()
    {
        return this.visitorFaceoffWins;
    }
    /**
     * @return the homeFaceoffWins
     */
    public List<Faceoff> getHomeFaceoffWins()
    {
        return this.homeFaceoffWins;
    }
    /**
     * @param homeTeamId the homeTeamId to set
     */
    public void setHomeTeamId(String homeTeamId)
    {
        this.homeTeamId = homeTeamId;
    }
    /**
     * @return the homeTeamId
     */
    public String getHomeTeamId()
    {
        return homeTeamId;
    }
    /**
     * @param visitorTeamId the visitorTeamId to set
     */
    public void setVisitorTeamId(String visitorTeamId)
    {
        this.visitorTeamId = visitorTeamId;
    }
    /**
     * @return the visitorTeamId
     */
    public String getVisitorTeamId()
    {
        return visitorTeamId;
    }

    @Override
    public int compareTo(Game game)
    {
        // TODO Auto-generated method stub
        return this.id.compareTo(game.id);
    }

}
